﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using T.FAS.Runtime.ScheduleJob.Dao;
using T.FAS.Runtime.Metadata.Entity.ScheduleJob;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Metadata.SPI;
using T.ServiceComponent.Error;

namespace T.FAS.Runtime.ScheduleJob.Plugin
{
    public class ScheduleJobManager : AbsMetaDataManager, IMetaDataManager
    {
        ScheduleJobLogic sJobLogic = new ScheduleJobLogic();
        /// <summary>
        /// 新增元数据
        /// </summary>
        /// <param name="metaData"></param>
        public void Save(IMetaDataContent metaData)
        {
            Runtime.Metadata.Entity.ScheduleJob.ScheduleJob sJob = null;
            if (metaData != null && metaData is Runtime.Metadata.Entity.ScheduleJob.ScheduleJob)
            {
                sJob = metaData as Runtime.Metadata.Entity.ScheduleJob.ScheduleJob;
            }
            else
            {
                throw new ArgumentException("ScheduleJob Save方法参数有错误，请检查");
            }
            if (!string.IsNullOrEmpty(metaData.MetaDataID) && !metaData.MetaDataID.Equals(sJob.ID, StringComparison.OrdinalIgnoreCase))
            {
                sJob.ID = metaData.MetaDataID;
            }
            try
            {
                if (!CheckUnique(metaData))
                {
                    throw new Exception($"不满足唯一性验证，Code:{sJob.Code}");
                }
                sJobLogic.AddScheduleJob(sJob);
            }
            catch (Exception e)
            {
                throw new Exception("元数据保存失败", e);
            }
        }
        /// <summary>
        /// 删除元数据
        /// </summary>
        /// <param name="metaData"></param>
        public void Delete(IMetaDataContent metaData)
        {
            if (metaData == null || string.IsNullOrEmpty(metaData.MetaDataID))
                throw new ArgumentNullException("IMetaDataContent", "metaData参数为空或MetadataID为空");
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
                {
                    sJobLogic.DeleteScheduleJob(metaData.MetaDataID);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception("元数据删除失败", e);
            }
        }
        /// <summary>
        /// 获取元数据
        /// </summary>
        /// <param name="metaDataId"></param>
        /// <returns></returns>
        public IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            if (string.IsNullOrEmpty(metaDataId))
                throw new ArgumentNullException("metaDataId", "ScheduleJobID为空");
            var sJob = sJobLogic.GetScheduleJobByID(metaDataId);
            if (sJob != null)
            {
                sJob.MetaDataID = sJob.ID;
                sJob.MetaDataCode = sJob.Code;
                sJob.MetaDataName = sJob.Name;
            }
            return sJob;
        }

        #region 基类方法

        public MetaDataCompileResult Compile(IList<IMetaDataContent> metadatas)
        {
            return new MetaDataCompileResult();
        }

        public ConflictMessage ConflictCheck(List<IMetaDataContent> releasedMetaData, IMetaDataContent releaseingMetaData)
        {
            return new ConflictMessage();
        }


        public IMetaDataContent DeserializeObject(string metaDataString, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                //var setting = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore };
                var sJob = JsonConvert.DeserializeObject<Runtime.Metadata.Entity.ScheduleJob.ScheduleJob>(metaDataString);
                return sJob;
            }
            else
            {
                throw new NotImplementedException();
            }
        }


        public void Release(IMetaDataContent metaData, ReleaseStrategy releaseStrategy)
        {

        }

        public void Release(IMetaDataContent metaData)
        {

        }


        public string SerializeObject(IMetaDataContent metadata, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                return JsonConvert.SerializeObject(metadata, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public void Update(IMetaDataContent metaData)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
                {
                    Delete(metaData);
                    Save(metaData);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new Exception($"元数据修改失败！\r\n元数据内容", e);
            }
        }

        public ValidateResult Validate(IMetaDataContent metaData)
        {
            return new ValidateResult();
        }

        public IList<MetaDataExportContent> Export(params IMetaDataContent[] metaDataList)
        {
            var contents = new List<MetaDataExportContent>();

            foreach (var item in metaDataList)
            {
                contents.Add(new MetaDataExportContent
                {
                    Content = this.SerializeObject(item, MetadataSerializeType.JSON),
                    ExportType = MetaDataExportType.JSON,
                    MetaDataId = item.MetaDataID,
                    MetaDataType = item.MetaData.MetaTypeID
                });
            }

            return contents;
        }

        public void Import(IList<MetaDataExportContent> contents, MetaDataImportStrategy importStrategy)
        {
            if (contents == null || contents.Count < 1)
                return;
            if (importStrategy == MetaDataImportStrategy.Delete)
            {
                DeleteMetadata(contents);
            }
            else
            {
                ImportMetadata(contents);
            }
        }

        private void DeleteMetadata(IList<MetaDataExportContent> contents)
        {
            if (contents != null && contents.Count > 0)
            {
                try
                {
                    using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
                    {
                        foreach (var content in contents)
                        {
                            this.sJobLogic.DeleteScheduleJob(content.MetaDataId);
                        }
                        scope.Complete();
                    }
                }
                catch (Exception ex)
                {
                    throw new FasException(ScheduleJobExceptionCode.ExecuteError, $"元数据删除失败", ex);
                }
            }
        }

        private void ImportMetadata(IList<MetaDataExportContent> contents)
        {
            var list = new List<IMetaDataContent>();
            foreach (var exportContent in contents)
            {
                var content = this.DeserializeObject(exportContent.Content, MetadataSerializeType.JSON);
                var sJob = content as Runtime.Metadata.Entity.ScheduleJob.ScheduleJob;
                if (sJob!=null &&  string.IsNullOrEmpty(sJob.ID))
                    sJob.ID = exportContent.MetaDataId;
                list.Add(content);
            }

            using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
            {
                this.Import(list);

                scope.Complete();
            }
        }

        private void Import(List<IMetaDataContent> metaDatas)
        {
            var jobList = new List<Runtime.Metadata.Entity.ScheduleJob.ScheduleJob>();
            foreach (var metaData in metaDatas)
            {
                var dataObject = metaData as Runtime.Metadata.Entity.ScheduleJob.ScheduleJob;
                if (dataObject == null)
                {
                    throw new FasException(ScheduleJobExceptionCode.ArgumentNullError, "元数据类型不是ScheduleJob, 实际类型:" + metaData.GetType().FullName);
                }

                jobList.Add(dataObject);
            }
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
                {
                    foreach (var sJob in jobList)
                    {
                        this.sJobLogic.DeleteScheduleJob(sJob.ID);
                        this.sJobLogic.AddScheduleJob(sJob);
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(ScheduleJobExceptionCode.MetadataImportError, "元数据导入失败", e);
            }
        }

        public void Enable(params IMetaDataContent[] metaData)
        {

        }
        /// <summary>
        /// 获取当前元数据依赖谁
        /// </summary>
        /// <param name="metaDataContent"></param>
        /// <returns></returns>
        public List<MetaDataDependency> GetMetaDataDependencys(IMetaDataContent metaDataContent)
        {
            return DependencyManager.GetMetaDataDependencys(metaDataContent);
        }

        /// <summary>
        /// 当前元数据变更需要通知出去的变更信息(MetaUpdateType定义的枚举项,需要在这里处理)
        /// </summary>
        /// <param name="oldMetaData"></param>
        /// <param name="newMetaData"></param>
        /// <returns></returns>
        public MetaDataUpdateSet GetMetaDataUpdateSet(IMetaDataContent oldMetaData, IMetaDataContent newMetaData)
        {
            return DependencyManager.GetMetaDataUpdateSet(oldMetaData,newMetaData);
        }

        /// <summary>
        /// 其他元数据变更通知到当前元数据,当前元数据对变更的响应逻辑
        /// </summary>
        /// <param name="metaDataContent"></param>
        /// <param name="updateSet"></param>
        /// <returns></returns>
        public MetaUpdateResult UpdateDependencyMetaData(IMetaDataContent metaDataContent, MetaDataUpdateSet updateSet)
        {
            return DependencyManager.UpdateDependencyMetaData(metaDataContent,updateSet);
        }

        public IRefSchemaEntity BuildRefSchema(IMetaDataContent metaDataContent)
        {
            return default;
        }

        public IEnumerable<Metadata.Entity.Term> BuildTerms(IMetaDataContent metaDataContent, IEnumerable<Metadata.Entity.Term> termList = null)
        {
            return default;
        }

        public IRefSchemaEntity DeserializeRefSchemaEntity(string schemaEntityJson)
        {
            return default;
        }

        ValidateResult IMetaDataManager.CompatibleValidate(IMetaDataContent metaData, IMetaDataContent oldMetaData)
        {
            return new ValidateResult { state = "1" };
        }
        public override MetaGenerateCodeResult GenerateCode(IMetaDataContent metadata, bool isInternational)
        {
            return new MetaGenerateCodeResult { IsSuccess = true };
        }
        #endregion

    }
}
